package com.wyj.interceptor;

import com.wyj.pojo.LoginTicket;
import com.wyj.pojo.User;
import com.wyj.service.UserService;
import com.wyj.service.imp.UserServiceImp;
import com.wyj.util.CookieUtil;
import com.wyj.util.HostHolder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.context.SecurityContextImpl;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;

/**
 * @author 王永杰
 * @Description 描述该类的做什么用
 * @since 2022/7/7
 */
@Component
public class LoginTicketInterceptor implements HandlerInterceptor {

    @Autowired
    UserServiceImp userServiceImp;

    @Autowired
    HostHolder hostHolder;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String ticket = CookieUtil.getValue(request, "ticket");
        if (ticket != null) {
            LoginTicket loginTicket = userServiceImp.getLoginTicket(ticket);

            //查看凭证是否有效 过期时间在 new Date()的后面
            if (loginTicket != null && loginTicket.getStatus() == 0 && loginTicket.getExpired().after(new Date())) {
                User user = userServiceImp.getUserById(loginTicket.getUserId());
                //本次请求中持有用户
                hostHolder.setUser(user);

                //构建用户认证的结果 将其存进  SecurityContext中，以便于Security获取
                Authentication authentication = new UsernamePasswordAuthenticationToken(
                        user, user.getPassword(), userServiceImp.getAuthorities(user.getId()));
                //认证结果存放 每次访问其他资源的请求时候  都会检查在SecurityContent中是否存在认证结果  所以我们在退出的时候需要销毁认证结果
                SecurityContextHolder.setContext(new SecurityContextImpl(authentication));

            }
        }


        return true;
    }

    //在Controller执行之后 这个就是 我们还没走Controller的返回 之前 那么我们添加一个model中的key值
    //那么的话  我们每次调转页面 之后 我们都可以 获得一个key对应的value
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        User user = hostHolder.getUser();

        if (user != null && modelAndView != null) {
            modelAndView.addObject("loginUser",user);
        }
    }

    //这里的话是完成请求页面 跳转 之后  那么的话 我们就需要 在多线程中销毁这个线程
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        hostHolder.clear();
    }
}
